<?php

namespace Biz\module\Behaviors;

use Biz\cache\Goods;
use Biz\cache\Sku;
use Biz\model\GoodsBasicInfo;
use Biz\module\Behaviors\Stock\GoodsSkuStock;
use Biz\module\Behaviors\Stock\LimitTimeStock;
use Biz\module\Behaviors\Stock\PintuanStock;
use Biz\pockets\serviceTrait\_Async;
use Doraemon\tools\HhzClient;
use Doraemon\tools\Log;
use Biz\service\search\Goods as searchGoods;
use Biz\cache\GoodsBasicInfo as cGoodsBasicInfo;
use Biz\module\Behaviors\Stock\AllActivityStock as sAllActivityStock;
use Biz\pockets\constInterface\ActivityInfo;

class StockBehavior
{

	use _Async;

    private static function _IniStockModel()
    {
        return [
            ActivityInfo::ACTIVITY_TYPE_NORMAL => GoodsSkuStock::class,
            ActivityInfo::ACTIVITY_TYPE_LIMIT_TIME_ROB => sAllActivityStock::class,
			ActivityInfo::ACTIVITY_TYPE_NEWCOMER_EXCLUSIVE => GoodsSkuStock::class,
			ActivityInfo::ACTIVITY_TYPE_WEEK_PURCHASE => GoodsSkuStock::class,
			ActivityInfo::ACTIVITY_TYPE_TUAN => GoodsSkuStock::class,
            ActivityInfo::ACTIVITY_TYPE_PINTUAN => sAllActivityStock::class,
            ActivityInfo::ACTIVITY_TYPE_ZHUYOUJINTIE => sAllActivityStock::class,
        ];
    }

    private static function _IniStockModelBak()
    {
        return [
            ActivityInfo::ACTIVITY_TYPE_NORMAL => GoodsSkuStock::class,
            ActivityInfo::ACTIVITY_TYPE_LIMIT_TIME_ROB => LimitTimeStock::class,
			ActivityInfo::ACTIVITY_TYPE_NEWCOMER_EXCLUSIVE => GoodsSkuStock::class,
			ActivityInfo::ACTIVITY_TYPE_WEEK_PURCHASE => GoodsSkuStock::class,
			ActivityInfo::ACTIVITY_TYPE_TUAN => GoodsSkuStock::class,
            ActivityInfo::ACTIVITY_TYPE_PINTUAN => PintuanStock::class

        ];
    }

    private static function _GroupByPromoType($buyNums, $needAdd = true)
    {

        $groupedInfos = [];

        $allowPromoType = [
            ActivityInfo::ACTIVITY_TYPE_PINTUAN,
            ActivityInfo::ACTIVITY_TYPE_LIMIT_TIME_ROB,
            ActivityInfo::ACTIVITY_TYPE_ZHUYOUJINTIE,
        ];

        foreach ($buyNums as $buyNum) {
        	$buyNum['action_uid'] = HhzClient::getUid();

            $groupedInfos[$buyNum['promo_type']][] = $buyNum;
            //如果商品中存在拼团与限时抢 附加减正常库存
            if ($needAdd && in_array($buyNum['promo_type'], $allowPromoType)) {
                $buyNum['promo_type'] = ActivityInfo::ACTIVITY_TYPE_NORMAL;
                $buyNum['promo_id'] = 0;
                $groupedInfos[ActivityInfo::ACTIVITY_TYPE_NORMAL][] = $buyNum;
            }
        }

        return $groupedInfos;

    }

    /*
     * $recentStock = [
            活动类型0 =>[
            [
                'goods_id' => 1,
                'buy_num' => 1,
            ],
            [
                'goods_id' => 2,
                'buy_num' => 2,
            ]
    ],
    活动类型9 => [
        [
            'goods_id' => 3,
            'buy_num' => 3,
        ]
    ]
        ];
     *
     * **/
    private static function updateDbStock($recentStock, $NumsGrpByPt, $is_incr = true)
    {
        $ModelMaps = self::_IniStockModel();

        foreach ($NumsGrpByPt as $promoType => $stockInfo)
        {
            foreach ($stockInfo as $key => $info)
            {
                $stockInfo[$key]['stock'] = $recentStock[$promoType][$info['sku_id']];
            }
            call_user_func_array([
                $ModelMaps[$promoType],
                __FUNCTION__
            ], [
                $stockInfo
            ]);
        }

        Log::debug('updateDbStock',[$recentStock, $NumsGrpByPt]);
//        $sell_stocks = [];
//        foreach ($NumsGrpByPt as $info) {
//            foreach ($info as $buyNums) {
//                $sell_stocks[(string)$buyNums['goods_id']][] = $buyNums['buy_num'];
//            }
//        }
//        $sell_stocks = array_map(function ($sells) {
//            return array_sum($sells);
//        }, $sell_stocks);
//
//        foreach ($sell_stocks as $goods_id => $sell_stock) {
//            if ($is_incr) {
//                $data = [
//                    'stock[+]' => $sell_stock,
//                    'sell_total[-]' => $sell_stock,
//                ];
//            } else {
//                $data = [
//                    'stock[-]' => $sell_stock,
//                    'sell_total[+]' => $sell_stock,
//                ];
//            }
//            GoodsBasicInfo::updateData($data, [
//                'goods_id' => $goods_id
//            ]);
//        }



        if (isset($NumsGrpByPt[ActivityInfo::ACTIVITY_TYPE_NORMAL])) {
            $sell_stocks = [];
            $stocks = [];
            foreach ($NumsGrpByPt[ActivityInfo::ACTIVITY_TYPE_NORMAL] as $buyNums) {
                $sell_stocks[(string)$buyNums['goods_id']][] = $buyNums['buy_num'];
            }

            $sell_stocks = array_map(function ($sells) {
                return array_sum($sells);
            }, $sell_stocks);


            foreach ($sell_stocks as $goods_id => $sell_stock) {
                if ($is_incr) {
                    $data = [
                        'stock[+]' => $sell_stock,
                        'sell_total[-]' => $sell_stock,
                    ];
                } else {
                    $data = [
                        'stock[-]' => $sell_stock,
                        'sell_total[+]' => $sell_stock,
                    ];
                }
                GoodsBasicInfo::updateData($data, [
                    'goods_id' => $goods_id
                ]);
            }

        }

    }


    public static function DecrStocksCounter($buyNums)
    {
        $ModelMaps = self::_IniStockModel();
        $NumsGrpByPt = self::_GroupByPromoType($buyNums);

        //扣减缓存中库存,并返回扣减后的值
        $recentStock = [];
        foreach ($NumsGrpByPt as $promoType => $subBuyNums) {
            $recentStock[$promoType] = call_user_func_array([
                $ModelMaps[$promoType],
                __FUNCTION__
            ], [
                $subBuyNums
            ]);
        }

        //扣减成负数,进行库存返还
        foreach ($recentStock as $promoType => $stocks) {
            foreach ($stocks as $sku_id => $stock) {
                if ($stock < 0) {
                    Log::Notice('库存不足 sku_id ' . $sku_id . " promotype: " . $promoType);
                    self::IncrStocksCounter($buyNums, false);
                    return false;
                }
            }
        }

        Log::order_createOrder_debug('扣减库存', compact('buyNums', 'ModelMaps', 'NumsGrpByPt', 'recentStock'));

		self::_async($recentStock, $NumsGrpByPt);

        return true;

    }

    public static function IncrStocksCounter($buyNums, $is_updateDb = true)
    {
        $ModelMaps = self::_IniStockModel();
        $NumsGrpByPt = self::_GroupByPromoType($buyNums, false);


        $recentStock = [];

        foreach ($NumsGrpByPt as $promoType => $subBuyNums) {

            self::setStocksCache(array_column($subBuyNums, 'goods_id'));

            $recentStock[$promoType] = call_user_func_array([
                $ModelMaps[$promoType],
                __FUNCTION__
            ], [
                $subBuyNums
            ]);

        }

        if ($is_updateDb) {
        	self::_async($recentStock, $NumsGrpByPt);

        }

        return true;

    }

    public static function _async_DecrStocksCounter($recentStock, $NumsGrpByPt)
    {
        $ModelMaps = self::_IniStockModel();

        self::updateDbStock($recentStock, $NumsGrpByPt, false);

        foreach ($NumsGrpByPt as $promoType => $buyNums) {
            $buyNums = array_map(function ($buyNum) use ($promoType, $recentStock){

//                //如果有限时抢商品 并且 其中有sku被买完 更新限时抢活动缓存
//                if ($promoType == ActivityInfo::ACTIVITY_TYPE_LIMIT_TIME_ROB && !$recentStock[$promoType][$buyNum['sku_id']]) {
//                    Activitys::setMultiRobbing([$buyNum['goods_id']]);
//                }

                //删除商品缓存
                Goods::delGoods($buyNum['goods_id']);
                cGoodsBasicInfo::delItem($buyNum['goods_id']);
                //删除skuinfo缓存
                Sku::delCache([], $buyNum['goods_id']);

                searchGoods::updateByGoodsId($buyNum['goods_id']);

                $buyNum['buy_num'] = -1 * abs($buyNum['buy_num']);
                return $buyNum;
            }, $buyNums);

//			($ModelMaps[$promoType])::addStockLog($buyNums, $recentStock[$promoType]);
            call_user_func_array(
                [$ModelMaps[$promoType], 'addStockLog'],
                [$buyNums, $recentStock[$promoType]]
            );
        }

    }

	public static function _async_IncrStocksCounter($recentStock, $NumsGrpByPt)
	{

		$ModelMaps = self::_IniStockModel();

		self::updateDbStock($recentStock, $NumsGrpByPt);

		foreach ($NumsGrpByPt as $promoType => $buyNums) {
			$buyNums = array_map(function ($buyNum) {

				//删除商品缓存
				Goods::delGoods($buyNum['goods_id']);
				cGoodsBasicInfo::delItem($buyNum['goods_id']);
				//删除skuinfo缓存
				Sku::delCache([], $buyNum['goods_id']);

				searchGoods::updateByGoodsId($buyNum['goods_id']);
				Sku::mDelItems($buyNum['goods_id']);
				$buyNum['buy_num'] = abs($buyNum['buy_num']);

				return $buyNum;
			}, $buyNums);
//			if ($promoType == ActivityInfo::ACTIVITY_TYPE_LIMIT_TIME_ROB) {
//				Activitys::setMultiRobbing(array_column($buyNums, 'goods_id'));
//			}

//			($ModelMaps[$promoType])::addStockLog($buyNums, $recentStock[$promoType]);
			call_user_func_array(
				[$ModelMaps[$promoType], 'addStockLog'],
				[$buyNums, $recentStock[$promoType]]
			);

		}

	}


    public static function setStocksCache($goods_ids)
    {

        $ModelMaps = self::_IniStockModel();

        $returnRst = [];
        foreach ($ModelMaps as $promoType => $stockModel) {
            $returnRst[$promoType] = call_user_func_array([
                $stockModel,
                __FUNCTION__
            ], [
                $goods_ids
            ]);
        }

        return $returnRst;

    }


}